using System;
using log4net;
using SpeakOut.Data.Interfaces;
using SpeakOut.Model;
using System.Collections.Generic;
using NHibernate.Criterion;
using NHibernate;

namespace SpeakOut.Data.NHibernate.Daos
{
    public class PostDao : BaseDao<Post>, IPostDao
    {
        private static readonly ILog _log = LogManager.GetLogger(typeof(PostDao));

        private ICriteria baseCriteria
        {
            get
            {
                return Session
                    .CreateCriteria<Post>()
                    .AddOrder(Order.Desc("PublishDate"));
            }
        }

        private ICriteria visibleCriteria
        {
            get
            {
                return baseCriteria
                    .Add(Expression.Eq("Published", true))
                    .Add(Expression.IsNotNull("PublishDate"));
            }
        }

        public IList<Post> FindAllVisible()
        {
            return visibleCriteria.List<Post>();
        }

        public IList<Post> FindRecentVisible(int quantity)
        {
            return visibleCriteria
                .SetMaxResults(quantity)
                .List<Post>();
        }

        public IList<Post> FindByMonth(int year, int month)
        {
            DateTime initDate = new DateTime(year, month, 1);
            DateTime endDate = initDate.AddMonths(1).AddDays(-1);
            _log.DebugFormat("Find posts between {0} and {1}", initDate.ToShortDateString(), endDate.ToShortDateString());
            
            return visibleCriteria
                .Add(Expression.Between("PublishDate", initDate, endDate))
                .List<Post>();
        }

        public Post FindByPermalink(string permalink, DateTime datePublished)
        {
            DateTime initDate = datePublished.Date;
            DateTime endDate = datePublished.Date.AddDays(1).AddSeconds(-1);
            return visibleCriteria
                .Add(Expression.Eq("Permalink", permalink).IgnoreCase())
                .Add(Expression.Between("PublishDate", initDate, endDate))
                .UniqueResult<Post>();
        }

        public IList<Post> FindByCategory(Guid id)
        {
            return visibleCriteria
                .CreateAlias("Categories", "category")
                .Add(Expression.Eq("category.CategoryId", id))
                .List<Post>();
        }

        public IList<Post> FindByTag(string tag)
        {
            return visibleCriteria
                .CreateAlias("Tags","tag")
                .Add(Expression.Eq("tag.Name", tag).IgnoreCase())
                .List<Post>();
        }
    }
}